﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Reflection;

namespace WGM_Client_Net35V2
{
    /// <summary>
    /// Class for holding local user's font data.
    /// Not critical, but helps to have a consisten look across all out going windows.
    /// </summary>
    public class LocalTextOptions : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        private System.Windows.Media.Color _myFontColour = System.Windows.Media.Colors.Black;
        private System.Windows.Media.FontFamily _myFontFamily = new System.Windows.Media.FontFamily("Verdana");
        private FontWeight _myFontWeight = FontWeights.Normal;
        private System.Windows.FontStyle _myFontStyle = FontStyles.Normal;
        private double _myFontSize = 10;

        public double MyFontSize
        {
            get { return _myFontSize; }
            set
            {
                _myFontSize = value;
                OnPropertyChanged("MyFontSize");
            }
        }         
        public System.Windows.FontStyle MyFontStyle
        {
            get { return _myFontStyle; }
            set
            {
                _myFontStyle = value;
                OnPropertyChanged("MyFontStyle");
            }
        }         
        public FontWeight MyFontWeight
        {
            get { return _myFontWeight; }
            set
            {
                _myFontWeight = value;
                OnPropertyChanged("MyFontWeight");
            }
        }         
        public System.Windows.Media.FontFamily MyFontFamily
        {
            get { return _myFontFamily; }
            set
            {
                _myFontFamily = value;
                OnPropertyChanged("MyFontFamily");
            }
        }
        public System.Windows.Media.Color MyFontColour
        {
            get { return _myFontColour; }
            set
            {
                _myFontColour = value;
                OnPropertyChanged("MyFontColour");
            }
        }
        /// <summary>
        /// Default Contstructer.
        /// </summary>
        public LocalTextOptions() { }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="uo">WGM online options to use.</param>
        public LocalTextOptions(WGM_Svc.UserOptions uo)
        {
            MyFontFamily = new System.Windows.Media.FontFamily(uo.UserFontFace);
            MyFontSize = uo.FontSize;
            if (uo.IsFontItalics)
                MyFontStyle = FontStyles.Italic;
            else
                MyFontStyle = FontStyles.Normal;
            if (uo.IsFontBold)
                MyFontWeight = FontWeights.Bold;
            else
                MyFontWeight = FontWeights.Regular;



            MyFontColour = HelperFunctions.GetNewColour(uo);
            OnPropertyChanged("MyFontFamily");
            OnPropertyChanged("MyFontSize");
            OnPropertyChanged("MyFontStyle");
            OnPropertyChanged("MyFontWeight");
            OnPropertyChanged("MyFontColour");
            OnPropertyChanged("MyFontDecorations");
            OnPropertyChanged("MyLocalTextOptions");
        }
         

    }
    /// <summary>
    /// Class to hold contact information to allow the UI to databind to its fields.
    /// </summary>
    public class ContactObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private const double CONTACT_DIMMED_OPACITY_ONLINE = 0.8;
        private const double CONTACT_DIMMED_OPACITY_OFFLINE = 0.5;
        private const double CONTACT_HAS_MESSAGES_OPACITY = 0.8;
        private const double CONTACT_IS_SELECTED_OPACITY = 1.0;
        private bool _isOnline;
        private WGMLocalEngine _wgmEngine;
        private string _contactDisplayName;
        private string _contactDisplayStatus;
        private string _contactUserName;
        private string _contactHighlighColour;
        private Visibility _contactStatusVisibility;
        private string _contactColour;
        private System.Windows.Controls.Border _contactDisplayImage = new System.Windows.Controls.Border();
        private bool _isSelected = false;
        private WGM_Svc.UserOptions _contactUserOptions;
        private string _contactTooltip;
        private string _contactDisplayString;
        private RichTextBox _outgoingTextBox = new System.Windows.Controls.RichTextBox();
        private RichTextBox _incomingTextBox = new System.Windows.Controls.RichTextBox();
        private bool _flashContact = false;
        private bool _showContact = true;
        private double _contactNameOpacity = CONTACT_IS_SELECTED_OPACITY;
        private bool _hasUnreadMessages = false;
        private string _localDisplayName;
        private string _localDisplayStatus;
        private Visibility _hasMessagesVisibility = Visibility.Collapsed;
        private ScrollViewer _incomingViewer = new ScrollViewer();

        /// <summary>
        /// The scroll viewer in which the incoming text is contained.
        /// </summary>
        public ScrollViewer IncomingViewer
        {
            get { return _incomingViewer; }
            set
            {
                _incomingViewer = value;
                OnPropertyChanged("IncomingViewer");
            }
        }
         
        /// <summary>
        /// Returns true if the contact object represents the local user.
        /// </summary>
        public bool ContactIsMe { get; private set; }
        /// <summary>
        /// Allows the UI to show an image in the contact list next to the contact if there is an ongoing conversation.
        /// </summary>
        public Visibility HasMessagesVisibility
        {
            get 
            {
                if (_incomingTextBox.Document.Blocks.Count > 0)
                    return Visibility.Visible;
                else
                    return Visibility.Collapsed;
            }
            set 
            { 
                _hasMessagesVisibility = value;
                OnPropertyChanged("HasMessagesVisibility");
            }
        }
        /// <summary>
        /// Returns true if the contact has a new message waiting to be read.
        /// </summary>         
        public bool HasUnreadMessages
        {
            get { return _hasUnreadMessages; }
            set
            {
                if (value != _hasUnreadMessages)
                {
                    _hasUnreadMessages = value;
                    OnPropertyChanged("HasUnreadMessages");
                    _wgmEngine.TabHasUnreadChanged(this);
                }
            }
        }
        public double ContactNameOpacity
        {
            get { return _contactNameOpacity; }
            set
            {
                _contactNameOpacity = value;
                OnPropertyChanged("ContactNameOpacity");
            }
        }
        public bool ShowContact
        {
            get { return _showContact; }
            set
            {
                _showContact = value;
                OnPropertyChanged("ShowContact");
            }
        }         
        public bool FlashContact
        {
            get { return _flashContact; }
            set
            {
                _flashContact = value;
                OnPropertyChanged("FlashContact");
            }
        } 
        public Visibility ContactStatusVisibility
        {
            get { return _contactStatusVisibility; }
            set
            {
                _contactStatusVisibility = value;
                OnPropertyChanged("ContactStatusVisibility");
            }
        }         
        public string ContactUserName
        {
            get { return _contactUserName; }
        }        
        public string ContactHighlightColour
        {
            get { return _contactHighlighColour; }
            set
            {
                _contactHighlighColour = value;
                OnPropertyChanged("ContactHighlightColour");
            }
        }  
        public string ContactColour
        {
            get 
            {
                if (ContactUserOptions != null)
                    return HelperFunctions.GetNewColour(ContactUserOptions).ToString();
                else
                    return Colors.Green.ToString();
            }
            set
            {
                _contactColour = value;
                OnPropertyChanged("ContactColour");
            }
        }
        public bool IsMainWindow { get; private set; }        
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                _isSelected = value;
                OnPropertyChanged("IsSelected");
                _wgmEngine.TabSelectionChanged(this);
                if (value == true)
                {
                    FlashContact = false;
                    ContactNameOpacity = CONTACT_IS_SELECTED_OPACITY;
                    
                }
                else
                {
                    if (ContactIsOnline)
                        ContactNameOpacity = CONTACT_DIMMED_OPACITY_ONLINE;
                    else if (HasMessagesVisibility == Visibility.Visible)
                        ContactNameOpacity = CONTACT_HAS_MESSAGES_OPACITY;
                    else
                        ContactNameOpacity = CONTACT_DIMMED_OPACITY_OFFLINE;
                }
            }
        }  
        public System.Windows.Controls.RichTextBox IncomingTextBox
        {
            get { return _incomingTextBox; }
            set
            {
                _incomingTextBox = value;
                OnPropertyChanged("IncomingTextBox");
            }
        }         
        public System.Windows.Controls.RichTextBox OutgoingTextBox
        {
            get { return _outgoingTextBox; }
            set
            {
                _outgoingTextBox = value;
                OnPropertyChanged("OutgoingTextBox");
            }
        }  
        public string ContactDisplayString
        {
            get { return HelperFunctions.GetCLToolTip(ContactUserOptions); }
            set
            {
                _contactDisplayString = value;
                OnPropertyChanged("ContactDisplayString");
            }
        }         
        public string ContactTooltip
        {
            get 
            {
                if (!IsMainWindow)
                    return (HelperFunctions.GetCLToolTip(ContactUserOptions) + ((!ContactIsOnline && !ContactIsMe)?(" \r\n"+ContactDisplayName+" is offline, messages sent will be received when "+ContactDisplayName+ " comes online"):"" ));
                else
                    return "Main Conversation window\r\nGroup messages are displayed here";
                
            }
            set
            {
                _contactTooltip = value;
                OnPropertyChanged("ContactTooltip");
            }
        }         
        public WGM_Svc.UserOptions ContactUserOptions
        {
            get { return _contactUserOptions; }
            set
            {
                _contactUserOptions = value;
                ContactDisplayName = value.DisplayName;
                ContactDisplayStatus = value.UserStatus;
                ContactColour = HelperFunctions.GetNewColour(value).ToString();
                OnPropertyChanged("ContactUserOptions");

            }
        }
        public System.Windows.Controls.Border ContactDisplayImage
        {
            get { return _contactDisplayImage; }
            set
            {
                _contactDisplayImage = value;
                OnPropertyChanged("DisplayImage");
            }
        }         
        public string ContactDisplayStatus
        {
            get { return _contactDisplayStatus; }
            set
            {
                _contactDisplayStatus = value;
                OnPropertyChanged("ContactDisplayStatus");
                OnPropertyChanged("ContactTooltip");
                OnPropertyChanged("ContactDisplayString");
                if (value == null || value.Trim() == "")
                {
                    //ContactStatusVisibility = Visibility.Collapsed;
                }
                else
                {
                    ContactStatusVisibility = Visibility.Visible;
                }
            }
        }         
        public bool ContactIsOnline
        {
            get { return _isOnline; }
            set
            {
                _isOnline = value;
                OnPropertyChanged("ContactIsOnline");
                OnPropertyChanged("ContactTooltip");
                OnPropertyChanged("ContactDisplayString");
                if (value == true)
                {
                    ContactHighlightColour = Colors.LimeGreen.ToString();
                    if (IsSelected)
                        ContactNameOpacity = CONTACT_IS_SELECTED_OPACITY;
                    else if (HasMessagesVisibility == Visibility.Visible)
                        ContactNameOpacity = CONTACT_HAS_MESSAGES_OPACITY;
                    else
                        ContactNameOpacity = CONTACT_DIMMED_OPACITY_ONLINE;
                }
                else
                {
                    ContactHighlightColour = Colors.DarkGray.ToString();
                    if (IsSelected)
                        ContactNameOpacity = CONTACT_IS_SELECTED_OPACITY;
                    else if (HasMessagesVisibility == Visibility.Visible)
                        ContactNameOpacity = CONTACT_HAS_MESSAGES_OPACITY;
                    else
                        ContactNameOpacity = CONTACT_DIMMED_OPACITY_OFFLINE;
                }
            }
        }        
        public string ContactDisplayName
        {
            get { return _contactDisplayName; }
            set
            {
                if (value.Trim() == "")
                    _contactDisplayName = ContactUserName;
                else
                    _contactDisplayName = value;
                OnPropertyChanged("ContactTooltip");
                OnPropertyChanged("ContactDisplayString");
                OnPropertyChanged("ContactDisplayName");
            }
        }         
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public ContactObject(string contactDisplayName, string contactDisplayStatus, string contactUserName, WGM_Svc.UserOptions userOptions, bool isMainWindow,bool contactIsMe, WGMLocalEngine engine)
        {
            IsMainWindow = isMainWindow;
            _wgmEngine = engine;
            ContactIsMe = contactIsMe;
            ContactDisplayName = contactDisplayName;
            ContactDisplayStatus = contactDisplayStatus;
            _contactUserName = contactUserName;
            _contactUserOptions = userOptions;
            _outgoingTextBox.VerticalScrollBarVisibility = System.Windows.Controls.ScrollBarVisibility.Auto;
            _incomingTextBox.VerticalScrollBarVisibility = System.Windows.Controls.ScrollBarVisibility.Disabled;
            _incomingViewer.Content = _incomingTextBox;
            _incomingTextBox.BorderThickness = new Thickness(0);
            _incomingTextBox.IsReadOnly = true;
            _incomingTextBox.SpellCheck.IsEnabled = true;
            _outgoingTextBox.SpellCheck.IsEnabled = true;
            _outgoingTextBox.BorderThickness = new Thickness(0);
            _outgoingTextBox.IsDocumentEnabled = true;
            _incomingTextBox.IsDocumentEnabled = true;
            _incomingTextBox.Document.Blocks.Clear();
            _incomingTextBox.Document.LineHeight = _outgoingTextBox.Document.LineHeight = 1;
            _incomingViewer.Background = new SolidColorBrush(Colors.White);
            _incomingViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;

            //FontStyle="{Binding Path=MyFontStyle}" FontSize="{Binding Path=MyFontSize}" FontWeight="{Binding Path=MyFontWeight}" FontFamily="{Binding Path=MyFontFamily}" Foreground="{Binding Path=MyFontColour}"

            
           
            ContactIsOnline = false;

            ContactDisplayImage.CornerRadius = new CornerRadius( 5);


            if (isMainWindow)
            {
                ContactColour = Colors.Green.ToString();
                ContactIsOnline = true;
                ContactDisplayImage.Background = new ImageBrush(new BitmapImage(new Uri(System.Windows.Forms.Application.StartupPath + "\\images\\mainicon2.png", UriKind.RelativeOrAbsolute)));
                OnPropertyChanged("ContactDisplayImage");
            }
            else
            {
                ContactColour = HelperFunctions.GetNewColour(userOptions).ToString();
                ContactDisplayImage.Background = new ImageBrush(new BitmapImage(new Uri(System.Windows.Forms.Application.StartupPath + "\\images\\blank.png", UriKind.RelativeOrAbsolute)));
            }
            SetLocalFontSettings();
        }
        public void SetLocalFontSettings()
        {
            _outgoingTextBox.Foreground = new SolidColorBrush(_wgmEngine.MyLocalTextOptions.MyFontColour);
            _outgoingTextBox.FontWeight = _wgmEngine.MyLocalTextOptions.MyFontWeight;
            _outgoingTextBox.FontStyle = _wgmEngine.MyLocalTextOptions.MyFontStyle;
            _outgoingTextBox.FontSize = _wgmEngine.MyLocalTextOptions.MyFontSize;
            _outgoingTextBox.FontFamily = _wgmEngine.MyLocalTextOptions.MyFontFamily;
        }
        public void StartFlashContact()
        {
            if (IsSelected == false)
            {
                FlashContact = false;
                FlashContact = true;
                OnPropertyChanged("IncomingTextBox");
                HasUnreadMessages = true;


            }
        }
        public void SetContactImage(BitmapImage source)
        {
            ContactDisplayImage.Background = new ImageBrush( source);
            OnPropertyChanged("ContactDisplayImage");
            
        }
        public void RemoveContactImage()
        {
            ContactDisplayImage.Background = ContactDisplayImage.Background = new ImageBrush(new BitmapImage(new Uri(System.Windows.Forms.Application.StartupPath + "\\images\\blank.png", UriKind.RelativeOrAbsolute)));
            OnPropertyChanged("ContactDisplayImage");
        }
        public void ClearMessages()
        {
            
            _incomingTextBox.Document.Blocks.Clear();
            OnPropertyChanged("HasMessagesVisibility");
        }


        internal void ClearUnreadMessage()
        {
            HasUnreadMessages = false;
        }
    }

    public class NetworkObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private string _networkName;
        private string _networDescription;
        private bool _isPasswordProtected;
        private int _networkMembersCount;
        private string _networkCreator;
        private DateTime _networkCreationDate;
        private bool _userIsMember;
        private Visibility _passwordBoxVisibility;
        private string _enterButtonText;
        private string _networkColour;
        private string _networkStatusMessage;
        private Visibility _networkStatusVisibilit;
        public Visibility NetworkStatusVisibility
        {
            get { return _networkStatusVisibilit; }
            set
            {
                _networkStatusVisibilit = value;
                OnPropertyChanged("NetworkStatusVisibility");
            }
        }
         
        public string NetworkStatusMessage
        {
            get { return _networkStatusMessage; }
            set
            {
                _networkStatusMessage = value;
                OnPropertyChanged("NetworkStatusMessage");
            }
        }
         
        public string NetworkColour
        {
            get { return _networkColour; }
            set
            {
                _networkColour = value;
                OnPropertyChanged("NetworkColour");
            }
        }
         
        private string _networkPassword;
        public string NetworkPassword
        {
            get { return _networkPassword; }
            set
            {
                _networkPassword = value;
                OnPropertyChanged("NetworkPassword");
            }
        }
         
        public string EnterButtonText
        {
            get { return _enterButtonText; }
            set
            {
                _enterButtonText = value;
                OnPropertyChanged("EnterButtonText");
            }
        }
         
        public Visibility PasswordBoxVisibility
        {
            get { return _passwordBoxVisibility; }
            set
            {
                _passwordBoxVisibility = value;
                OnPropertyChanged("PasswordBoxVisibility");
            }
        }
         
        public bool UserIsMember
        {
            get { return _userIsMember; }
            set
            {
                _userIsMember = value;
                OnPropertyChanged("UserIsMember");
            }
        }
         
        public DateTime NetworkCreationDate
        {
            get { return _networkCreationDate; }
            set
            {
                _networkCreationDate = value;
                OnPropertyChanged("NetworkCreationDate");
            }
        }
         
        public string NetworkCreator
        {
            get { return _networkCreator; }
            set
            {
                _networkCreator = value;
                OnPropertyChanged("NetworkCreator");
            }
        }
        
        public NetworkObject(string name, string description,string creator, DateTime creationDate, bool isPasswordProtected,bool userIsMember, int membersCount)
        {
            NetworkName = name;
            NetworkDescription = description;
            NetworkMembersCount = membersCount;
            NetworkCreator = creator;
            NetworkCreationDate = creationDate;
            UserIsMember = userIsMember;
            IsPasswordProtected = isPasswordProtected;
            NetworkPassword = "";
            RemoveStatusMessage();
            if (UserIsMember)
            {
                PasswordBoxVisibility = Visibility.Collapsed;
                NetworkColour = Colors.LimeGreen.ToString();
                EnterButtonText = "Enter Network";
            }
            else if (!IsPasswordProtected && !UserIsMember)
            {
                PasswordBoxVisibility = Visibility.Collapsed;
                NetworkColour = Colors.Yellow.ToString();
                EnterButtonText = "Join Network";
            }
            else if(IsPasswordProtected && !UserIsMember)
            {
                NetworkColour = Colors.Salmon.ToString();
                PasswordBoxVisibility = Visibility.Visible;
                EnterButtonText = "Join Network";
            }

        }

        public int NetworkMembersCount
        {
            get { return _networkMembersCount; }
            set
            {
                _networkMembersCount = value;
                OnPropertyChanged("NetworkMembersCount");
            }
        }         
        public bool IsPasswordProtected
        {
            get { return _isPasswordProtected; }
            set
            {
                _isPasswordProtected = value;
                OnPropertyChanged("IsPasswordProtected");
            }
        }         
        public string NetworkDescription
        {
            get { return _networDescription; }
            set
            {
                _networDescription = value;
                OnPropertyChanged("NetworkDescription");
            }
        }         
        public string NetworkName
        {
            get { return _networkName; }
            set
            {
                _networkName = value;
                OnPropertyChanged("NetworkName");
            }
        }
        public void SetStatusMessage(string message)
        {
            NetworkStatusVisibility = Visibility.Visible;
            NetworkStatusMessage = message;
        }
        public void RemoveStatusMessage()
        {
            NetworkStatusVisibility = Visibility.Collapsed;
            NetworkStatusMessage = "";
        }
         
    }
    public interface IMainWindow
    {
        void LoginCompleted(bool result, string message, bool isReconnect);

        void LogoffCompleted();

        void ContactChangedOnlineStatus(ContactObject co);

        void MessageRetrievalCompleted(WGM_Client_Net35V2.WGM_Svc.WGMMessage[] wGMMessage, bool success, string statusMessage);

        void HandleError(Exception ex);

        void ReceiveTextMessage(ContactObject destination,ContactObject sender, WGM_Client_Net35V2.WGM_Svc.WGMMessage message);

        void MyContactObjectChanged();

        void MyDisplayImageChanged();

        void ShowAndSelect(ContactObject _destination);

        void StartupCompleted(bool success);

        void TabSelectionChanged(ContactObject contactObject);

        void TabHasUnreadChanged(ContactObject contactObject);

        void NetworksRetrievalCompleted(bool success, string statusMessage);

        void NetWorkJoinCompleted(bool success, string message);
    }
}
